/* #include <inttypes.h> */
#include <my_header.h>
/* #include "../include/client.h" */

typedef struct train_s{
    int type;
    int length;
    char data[1000];
}train_t;

int recvn(int sockfd,void *buf,int length){
    int total=0;
    char * p=(char *)buf;
    while(total<length){
        int ret=recv(sockfd,p+total,length-total,0);
        total+=ret;
    }
    return 0;
}

/* int c_recv_download(int sockfd,char *filename){ */
int c_recv_download(int sockfd,char *filename){
    train_t train;
    int size=0;
    if(access(filename,F_OK)==0){ // 文件存在就断点续传
        printf("我是断点续传\n");
        train.type=11;
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);

    // 执行断点续传逻辑
        // 发文件名
        train.type=0;
        train.length=strlen(filename);
        memcpy(train.data,filename,train.length);
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,train.data,train.length,MSG_NOSIGNAL);

        // 发断点文件大小
        struct stat statbuf;
        stat(filename,&statbuf);
        size=statbuf.st_size;
        printf("size=%d\n",size);
        train.type=0;
        train.length=sizeof(size);
        memcpy(train.data,&size,train.length);
        /* memcpy(train.data,&size,sizeof(size)); */
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,train.data,train.length,MSG_NOSIGNAL);

        // 收实际文件大小
        int filesize=0;
        recvn(sockfd,&train.type,sizeof(train.type));
        recvn(sockfd,&train.length,sizeof(train.length));
        recvn(sockfd,train.data,train.length);
        memcpy(&filesize,train.data,train.length);
        printf("filesize=%d\n",filesize);


        // 收文件
        int fd=open(filename,O_RDWR|O_CREAT|O_APPEND,0666);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                /* if(train.length==0) break; */
                recvn(sockfd,&train.type,sizeof(train.type));
                recvn(sockfd,&train.length,sizeof(train.length));
                /* if(train.length==0) break; */
                recvn(sockfd,train.data,train.length);
                if(train.length==0) break;
                write(fd,train.data,train.length);
            }
        }else{
            printf("我是mmap\n");
            ftruncate(fd,filesize);
            char *p=(char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
            recvn(sockfd,p+size,filesize-size);
            /* write(fd,p,filesize-size); */
            munmap(p,filesize-size);
            printf("666\n");
        }
        close(fd);
        return 0;
    }else{ //不存在就正常传
        printf("我是普通文件发送\n");
        train.type=22;
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        // 执行正常逻辑
        // 发文件名
        train.type=0;
        train.length=sizeof(filename);
        memcpy(train.data,filename,train.length);
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,train.data,train.length,MSG_NOSIGNAL);

        // 收实际文件大小
        int filesize=0;
        recvn(sockfd,&train.type,sizeof(train.type));
        recvn(sockfd,&train.length,sizeof(train.length));
        recvn(sockfd,train.data,train.length);
        memcpy(&filesize,train.data,train.length);
        printf("filesize=%d\n",filesize);


        // 收文件
        int fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));    
                /* if(train.length==0) break; */
                recvn(sockfd,&train.type,sizeof(train.type));
                recvn(sockfd,&train.length,sizeof(train.length));
                /* if(train.length==0) break; */
                recvn(sockfd,train.data,train.length);
                if(train.length==0) break;
                write(fd,train.data,train.length);
            }   
        }else{
            printf("我是mmap\n");
            ftruncate(fd,filesize);
            char *p=(char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
            recvn(sockfd,p,filesize);
            /* write(sockfd,p,filesize); */
            munmap(p,filesize);
        }
        return 0;
    }
    return 0;
}

int c_up(int sockfd,char *filename){
    /* char *filename="1.txt"; */
    printf("111111111\n");
    train_t train;
    // 发文件名
    train.type=0;
    train.length=strlen(filename);
    memcpy(train.data,filename,train.length);
    send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
    send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
    send(sockfd,train.data,train.length,MSG_NOSIGNAL);

    recvn(sockfd,&train.type,sizeof(train.type));
    if(train.type==11){ // 断点续传
        // 收断点文件大小                                            
        int size=0;
        recvn(sockfd,&train.type,sizeof(train.type));
        recvn(sockfd,&train.length,sizeof(train.length));
        recvn(sockfd,train.data,train.length);
        memcpy(&size,train.data,train.length);
        printf("size=%d\n",size);

        // 算实际文件大小
        struct stat statbuf;
        stat(filename,&statbuf);
        int filesize=statbuf.st_size;
        printf("filesize=%d\n",filesize);
        train.type=0;
        train.length=sizeof(filesize);
        memcpy(train.data,&filesize,train.length);
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,train.data,train.length,MSG_NOSIGNAL);

        // 从断点处开始发文件
        int fd=open(filename,O_RDWR);
        lseek(fd,size,SEEK_SET);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                int ret=read(fd,train.data,sizeof(train.data));
                train.length=ret;
                train.type=0;
                send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
                send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
                send(sockfd,train.data,train.length,MSG_NOSIGNAL);
                if(ret==0) break;
            }
        }else{
            printf("我是mmap\n");
            sendfile(sockfd,fd,NULL,filesize-size);
            printf("发完了\n");
        }
        return 0;
    }else if(train.type==22){ // 正常上传
        // 算实际文件大小
        struct stat statbuf;
        stat(filename,&statbuf);
        int filesize=statbuf.st_size;
        printf("filesize=%d\n",filesize);
        train.type=0;
        train.length=sizeof(filesize);
        memcpy(train.data,&filesize,train.length);
        send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,train.data,train.length,MSG_NOSIGNAL);


        int fd=open(filename,O_RDWR);
        ERROR_CHECK(fd,-1,"open");
        if(filesize<10){
            while(1){                                              
                bzero(train.data,sizeof(train.data));
                int ret=read(fd,train.data,sizeof(train.data));
                /* if(ret==0) break; */
                train.length=ret;
                train.type=0;
                send(sockfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
                send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
                if(ret==0) break;
                send(sockfd,train.data,train.length,MSG_NOSIGNAL);
                printf("222222222222\n");
            }
        }else{
            printf("我是mmap\n");
            sendfile(sockfd,fd,NULL,filesize);
            printf("发完了\n");
        }
        printf("333333333333333\n");
        /* train.length=0; */
        /* send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL); */
        /* close(sockfd); */
        return 0;
    }

    return 0;
}


/* int main(int argc, char *argv[]){ */
/*     // ./client 192.168.18.128 12345 */                                       
/*     ARGS_CHECK(argc,3); */
/*     printf("555\n"); */
/*     int sockfd=socket(AF_INET,SOCK_STREAM,0); */
/*     printf("333\n"); */
/*     struct sockaddr_in addr; */
/*     addr.sin_family=AF_INET; */
/*     addr.sin_port=htons(atoi(argv[2])); */
/*     addr.sin_addr.s_addr=inet_addr(argv[1]); */
/*     printf("444\n"); */
/*     int ret=connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)); */
/*     printf("666\n"); */
/*     ERROR_CHECK(ret,-1,"connect"); */
/*     printf("lll\n"); */
/*     char filename[]="file1"; */
/*     /1* c_recv_download(sockfd,filename); *1/ */
/*     c_up(sockfd,filename); */
/*     /1* transfile(sockfd); *1/ */
/*     close(sockfd); */
/*     return 0; */
/* } */
